package com.yupi.yupicturebackend.manager.websocket.disruptor;

import com.lmax.disruptor.RingBuffer;
import com.lmax.disruptor.dsl.Disruptor;
import com.yupi.yupicturebackend.manager.websocket.disruptor.PictureEditEvent;
import com.yupi.yupicturebackend.manager.websocket.model.PictureEditRequestMessage;
import com.yupi.yupicturebackend.model.entity.User;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.WebSocketSession;

import javax.annotation.PreDestroy;
import javax.annotation.Resource;

@Component
@Slf4j
public class PictureEditEventProducer {

    @Resource
    Disruptor<PictureEditEvent> pictureEditEventDisruptor;

    /**
     * 发布事件
     * @param pictureEditRequestMessage
     * @param session
     * @param user
     * @param pictureId
     */
    public void publishEvent(PictureEditRequestMessage pictureEditRequestMessage, WebSocketSession session, User user, Long pictureId) {
        RingBuffer<PictureEditEvent> ringBuffer = pictureEditEventDisruptor.getRingBuffer();
        // 获取可以生成的位置 （存储在对应的索引位置）
        long next = ringBuffer.next();
        PictureEditEvent pictureEditEvent = ringBuffer.get(next);
        pictureEditEvent.setSession(session);
        pictureEditEvent.setPictureEditRequestMessage(pictureEditRequestMessage);
        pictureEditEvent.setUser(user);
        pictureEditEvent.setPictureId(pictureId);
        // 发布事件
        ringBuffer.publish(next);
    }

    /**
     * 优雅停机
     */
    @PreDestroy  // 当应用关闭时，@PreDestroy注解确保close方法被调用
    // 当Spring容器销毁Bean时（例如应用关闭或上下文被销毁时），标记了@PreDestroy的方法会被自动调用。   可以理解为是销毁PictureEditEventProducer的实例
    public void close() {
        // 调用pictureEditEventDisruptor.shutdown()方法，停止Disruptor框架中的事件处理流程，释放相关资源。
        pictureEditEventDisruptor.shutdown();
        /**
         * 如果没有调用pictureEditEventDisruptor.shutdown()，可能会导致以下问题：
         * 资源泄漏：Disruptor框架内部使用了线程池来处理事件。如果不显式调用shutdown()方法，这些线程不会被终止，可能导致线程资源无法释放，从而引发内存泄漏或线程资源耗尽的问题。
         * 事件处理未完成：shutdown()方法会确保所有已发布的事件被完全处理后再停止线程池。如果未调用shutdown()，可能会导致部分事件未被处理就直接中断程序运行。
         * 优雅停机失败：在应用关闭时，未正确释放资源可能导致后续启动或其他操作出现异常，影响系统的稳定性和可靠性。
         */
    }
}
